using System;
using System.Collections.Generic;
using System.Data.Linq;
using System.Linq.Expressions;

namespace SmartClientPlatform.RemoteClientBase
{
    [Serializable]
    public class DtoBase<TLinqToSqlObject>
    {
        private DataStore dataStore;

        internal DataContainer<TLinqToSqlObject> DataContainer
        {
            private get
            {
                DataContainer<TLinqToSqlObject> dataContainer;
                if (dataStore == null)
                {
                    dataContainer = CreateDataContainer();
                }
                else
                {
                    dataContainer = dataStore.Wrap(() => CreateDataContainer());
                }
                dataContainer.Wrap(() => this);
                return dataContainer;
            }
            set
            {
                dataStore = value.DataStore;
            }
        }

        private static DataContainer<TLinqToSqlObject> CreateDataContainer()
        {
            return new DataContainer<TLinqToSqlObject>();
        }

        protected T GetValue<T>(Expression<Func<TLinqToSqlObject, T>> expression)
        {
            return DataContainer.GetValue(expression);
        }

        protected T2 GetRef<T, T2>(Expression<Func<TLinqToSqlObject, T>> expression, Func<T2> func) 
            where T2 : DtoBase<T>
        {
            return DataContainer.GetRef(expression).Wrap(func);
        }

        protected void SetRef<T, T2>(Expression<Func<TLinqToSqlObject, T>> expression, T2 t2)
            where T2 : DtoBase<T>
        {
            DataContainer.SetRef(expression, t2.DataContainer);
        }

        protected IEnumerable<T2> GetValue<T, T2>(
            Expression<Func<TLinqToSqlObject, EntitySet<T>>> expression, Func<T2> func) 
            where T : class where T2 : DtoBase<T>
        {
            return DataContainer.GetValue(expression).Wrap(func);
        }

        protected void SetValue<T>(Expression<Func<TLinqToSqlObject, T>> expression, T value)
        {
            DataContainer.SetValue(expression, value);
        }
    }
}
